<?php

declare(strict_types = 1);

namespace NanQi\Hope\Listener;

use Hyperf\Database\Events\QueryExecuted;
use Hyperf\Database\Model\Events\Event;
use Hyperf\Database\Model\Events\Retrieved;
use Hyperf\Database\Model\Events\Saving;
use Hyperf\Event\Annotation\Listener;
use Hyperf\Utils\Arr;
use Hyperf\Utils\Context;
use Hyperf\Utils\Str;
use NanQi\Hope\Base\BaseListener;
use NanQi\Hope\Constants\StatusCodeConstants;
use NanQi\Hope\Db\SecretModel;
use NanQi\Hope\Helper;
use NanQi\Hope\Service\HashService;

class SecretModelListener extends BaseListener
{
    use Helper;

    public function listen() : array
	{
		return [
            Retrieved::class,
            Saving::class
		];
	}

	/**
	 * @param object $event
	 */
	public function process(object $event) : void
	{
        if (!$event instanceof Event) {
            return;
        }

        $model = $event->getModel();
        if (!$model instanceof SecretModel) {
            return;
        }

        $idFieldName = $model->idFieldName;
        if (!$model->$idFieldName) {
            return;
        }

        $signFieldName = $model->signFieldName;

        $data = $model->getSignData();
        $sign = $this->getSign($data, (string)$model->$idFieldName);
        $salt = config('hope.secret-salt', 'nanqi');
        if ($event instanceof Retrieved) {
            if (!$model->$signFieldName) {
                $this->errorDataError();
            }

            $str = '$2y$10$'.strtolower(md5($sign . $salt));
            if ($str != $model->$signFieldName) {
                $this->errorDataError();
            }
        }

        if ($event instanceof Saving) {
            $model->$signFieldName = '$2y$10$'.strtolower(md5($sign . $salt));
        }
	}

    private function getSign(array $data, string $sign_key)
    {
        ksort($data);

        $code = '';

        foreach ($data as $key => $val) {
            $code .= $key . ':' . $val . '|';
        }

        $code = '|' . $sign_key . '|' . $code;

        $code = md5($code);
        $result = strtoupper($code);

        return $result;
    }
}
